﻿//-----------------------------------------------------------------------
// <copyright file="Repository.cs" company="WpfDevelopment.com">
//     Copyright WpfDevelopment.com. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Hrmsystem.Data
{
    using System;
    using System.Data.Entity;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using System.Linq.Expressions;
    using WpfDevelopment.Data;
    using WpfDevelopment.MVVM;

    /// <summary>
    /// The global repository to persist objects
    /// </summary>
    public class Repository : IRepository
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Repository"/> class.
        /// </summary>
        /// <param name="unitOfWork">The unit of work.</param>
        public Repository(IUnitOfWork unitOfWork)
        {
            this.UnitOfWork = unitOfWork;
        }

        /// <summary>
        /// Gets the unit of work.
        /// </summary>
        /// <value>The unit of work.</value>
        public IUnitOfWork UnitOfWork
        {
            get;
            private set;
        }

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <typeparam name="T">The type of entity to add</typeparam>
        /// <param name="entity">The entity to add.</param>
        /// <returns>The added entity</returns>
        public T Add<T>(T entity) where T : ModelBase
        {
            this.UnitOfWork.Add(entity);
            return entity;
        }

        /// <summary>
        /// Updates the specified entity.
        /// </summary>
        /// <typeparam name="T">The type of entity to update</typeparam>
        /// <param name="entity">The entity to update.</param>
        /// <returns>The updated entity</returns>
        public T Update<T>(T entity) where T : ModelBase
        {
            this.UnitOfWork.Update(entity);
            return entity;
        }

        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <typeparam name="T">The type of entity to delete</typeparam>
        /// <param name="entity">The entity.</param>
        public void Delete<T>(T entity) where T : ModelBase
        {
            this.UnitOfWork.Delete(entity);
        }

        /// <summary>
        /// Gets this instance.
        /// </summary>
        /// <typeparam name="T">The type of entities to get</typeparam>
        /// <returns>An IQueryable of the type requested</returns>
        public IQueryable<T> Query<T>() where T : ModelBase
        {
            return (this.UnitOfWork.Context as DbContext).Set<T>();
        }

        /// <summary>
        /// Gets the specified query.
        /// </summary>
        /// <typeparam name="T">The type of entities to get</typeparam>
        /// <param name="queryStatement">The query to run against the data context.</param>
        /// <returns>An IQueryable of the type requested</returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Lambda expression")]
        public IQueryable<T> Query<T>(Expression<Func<T, bool>> queryStatement) where T : ModelBase
        {
            return this.Query<T>().Where(queryStatement);
        }

        /// <summary>
        /// Gets a single entity.
        /// </summary>
        /// <typeparam name="T">The type of entity to get</typeparam>
        /// <param name="primaryKey">The primary key.</param>
        /// <returns>The entity requested</returns>
        public T GetEntity<T>(object primaryKey) where T : ModelBase
        {
            return (this.Query<T>() as DbSet<T>).Find(primaryKey);
        }
    }
}
